-
Notifications
You must be signed in to change notification settings - Fork 677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sBTC Alpha Testnet Contract #3499
Conversation
Codecov Report
@@ Coverage Diff @@
## next #3499 +/- ##
==========================================
- Coverage 31.15% 31.06% -0.10%
==========================================
Files 305 305
Lines 276796 276796
==========================================
- Hits 86233 85982 -251
- Misses 190563 190814 +251
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
|
||
;; data vars | ||
;; | ||
(define-data-var coordinator (optional principal) none) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to just initialize coordinator
to be the intended principal from the get-go, instead of requiring the coordinator to call set-coordinator-key
?
This would also remove the need to represent coordinator
as an optional
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We were assuming that the principal deploying the contract would be an admin, but not necessarily the coordinator. And since we are going to need separate FROST public keys in addition to principals, I'm not sure there's a good way to set that on contract init.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we initialize coordinator to the contract admin/creator? The admin can later change it and this way the variable doesn't need to be optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we initialize coordinator to the contract admin/creator? The admin can later change it and this way the variable doesn't need to be optional.
No, because we need a FROST public key in addition to a principal.
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
We need to add a data member to store frost params N and T and ability for owner to reset these params. The signer set function should check the id is in [0,N]. Also, it may be useful to have functions to reset the contract-owner. Also, we need to a member variable to store the threshold wallet bitcoin address gated by the coordinator. |
|
||
;; private functions | ||
;; | ||
(define-private (is-valid-caller) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we rename to this function assert-tx-sender-is-owner!
and add assert-tx-sender-is-coordinator!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I named them is-contract-owner
and is-coordinator
since we might want to call them when we aren't doing an assert
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Could we have assert-is-contract-owner
call is-contract-owner
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting a weird clarinet check
error when I try to add these functions.
(define-private (assert-is-contract-owner) (asserts! (is-eq contract-owner tx-sender) (err err-invalid-caller)) )
detected two execution paths, returning two different expression types (got '(response UnknownType uint)' and 'bool')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, same error @igorsyl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I understand; I'm guessing that asserts!
in the true case returns true from the statement, and in the error case return err from the function. Since the compiler can't know which branch will be followed there is a conflict.
When using asserts!
in the body of a function, though, the statement return from asserts!
is ignored, but the function will return the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that was it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the following does work:
(define-private (assert-is-coordinator) (begin (asserts! (is-coordinator) (err err-invalid-caller)) (ok true) ) )
But this won't work if we replace the existing asserts!
calls, since we will now be returning a result in either case, and not immediately returning from the function in the error case. I'll still need to wrap in the same asserts!
to get the existing behavior.
Maybe if I made assert-is-contract-owner
a macro? Is this what the !
token indicates? What about the ?
token?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't work either:
(define-public (set-contract-owner (owner principal)) (begin (asserts-is-contract-owner!) (ok (var-set contract-owner owner)) ) )
(define-private (asserts-is-contract-owner!) (begin (asserts! (is-contract-owner) (err err-invalid-caller)) (ok true) ) )
Still gives a clarity error:
intermediary responses in consecutive statements must be checked
contrib/sbtc/token-key-admin/contracts/sbtc-token-key-admin.clar
Outdated
Show resolved
Hide resolved
Added |
signer set/delete now checks for valid id |
contract-owner is now a var and can be set |
What's the idiomatic way of storing a bitcoin address @igorsyl ? |
… add test that tries to transfer once trading is halted (currently fails in what appears to be infinite recursion
(define-public (mint! (amount uint) (memo (string-ascii 72))) | ||
(begin | ||
(asserts! (is-coordinator) (err err-invalid-caller)) | ||
(ft-mint? sbtc amount tx-sender) | ||
) | ||
) | ||
|
||
(define-public (burn! (amount uint) (memo (string-ascii 72))) | ||
(begin | ||
(asserts! (is-coordinator) (err err-invalid-caller)) | ||
(ft-burn? sbtc amount tx-sender) | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods should take an additional principal as an argument, since the coordinator will mint & burn tokens for arbitrary stacks principals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think memo
is meant to encode the bitcoin ops request txid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done @netrome
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See below @igorsyl , I used peg-in/out-txid for mint/burn
) | ||
) | ||
|
||
(define-public (burn! (amount uint) (memo (string-ascii 72))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we instead of calling it memo
call it peg_out_txid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, used peg-in/out-txid for mint/burn
The sbtc contract is being developed here. We will move it to this repository once it's stable. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Description
Add a simple contract to allow administering the coordinator and signer keys, and also allowing mint/burn/transfer of sBTC tokens.
Applicable issues
Additional info (benefits, drawbacks, caveats)
This contract is much more limited than the final one will be. It does not allow separate admins from the contract owner, and does not allow signers to rotate their keys. It also has neither a way to verify schnorr sigs, nor contract code to allow automatic peg handing once a threshold is reached.
Checklist
docs/rpc/openapi.yaml
andrpc-endpoints.md
for v2 endpoints,event-dispatcher.md
for new events)clarity-benchmarking
repobitcoin-tests.yml